[XENCONSOLE] reference of tty->count in xencons_close() is racy.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 10 Jul 2006 14:23:15 +0000 (15:23 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Mon, 10 Jul 2006 14:23:15 +0000 (15:23 +0100)
It must be protected by tty_sem semaphore like con_close() in
drivers/char/vt.c. and prevent re-opening this tty.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/console/console.c

index 2e1017a2240bc902fa5245da4679f3a3c048d74f..ff1cfe2d7e6cc4e3e203c0ae755e0bcc949cffe3 100644 (file)
@@ -536,18 +536,27 @@ static void xencons_close(struct tty_struct *tty, struct file *filp)
        if (DUMMY_TTY(tty))
                return;
 
-       if (tty->count == 1) {
-               tty->closing = 1;
-               tty_wait_until_sent(tty, 0);
-               if (DRV(tty->driver)->flush_buffer != NULL)
-                       DRV(tty->driver)->flush_buffer(tty);
-               if (tty->ldisc.flush_buffer != NULL)
-                       tty->ldisc.flush_buffer(tty);
-               tty->closing = 0;
-               spin_lock_irqsave(&xencons_lock, flags);
-               xencons_tty = NULL;
-               spin_unlock_irqrestore(&xencons_lock, flags);
+       down(&tty_sem);
+
+       if (tty->count != 1) {
+               up(&tty_sem);
+               return;
        }
+
+       /* Prevent other threads from re-opening this tty. */
+       set_bit(TTY_CLOSING, &tty->flags);
+       up(&tty_sem);
+
+       tty->closing = 1;
+       tty_wait_until_sent(tty, 0);
+       if (DRV(tty->driver)->flush_buffer != NULL)
+               DRV(tty->driver)->flush_buffer(tty);
+       if (tty->ldisc.flush_buffer != NULL)
+               tty->ldisc.flush_buffer(tty);
+       tty->closing = 0;
+       spin_lock_irqsave(&xencons_lock, flags);
+       xencons_tty = NULL;
+       spin_unlock_irqrestore(&xencons_lock, flags);
 }
 
 static struct tty_operations xencons_ops = {